package handler

import (
	log "github.com/sirupsen/logrus"
	"src/db"
	"src/handler/tools"
	"src/modle"
	"sync"
)

// 对于每个风控项的全局数据
type Data struct {
	Uid uint                    //用户uid
	C   *chan modle.DetailsType // 用户发送接受各个指标的结果数据
	G   *sync.WaitGroup         // 组任务，保证所有指标都执行且写入到对应的结构中
	Arr *[]modle.DetailsType    // 用于接受各个指标的结构
}

func (d Data) Run() error {
	// 用uid获取风控项数组
	ROArr, e := db.GetRiskOptionList(d.Uid)
	if e != nil {
		log.Error(e)
		return e
	}
	// 添加组任务，保证数据完整性
	// 添加和收录是两个对应的过程，so *2
	//d.G.Add(3 * 2)
	d.G.Add(len(ROArr) * 2)

	// 由于需求为每个风控项，独立可调整，所以此处switch了所有的开启的风控项
	// 独立使用goroutine并发运算
	for _, opt := range ROArr {
		// 不被OptMap包含的指标
		if !tools.Contains(OptMap, opt.Oid) {
			log.Error("OptMap不包含指标:", opt.Oid)
			continue
		}
		// 每个风控项oid映射一个对应的执行方法
		go OptMap[opt.Oid](d.C, d.G, d.Uid, opt)
	}

	go readChan(d.C, d.Arr, d.G)
	d.G.Wait()
	// 关闭
	defer close(*d.C)
	return nil
}

func readChan(ch *chan modle.DetailsType, arr *[]modle.DetailsType, sy *sync.WaitGroup) {
	for {
		//log.Debug("开始读channel")
		//读取通道方式, val,ok := <-chan 通道关闭后，ok是false
		j, ok := <-*ch
		if ok {
			//log.Debugf("channel中读到内容: %+v", j)
			*arr = append(*arr, j)
			sy.Done()
		} else {
			//log.Debugf("channel 已关闭")
			return
		}
	}
}
